#ifndef _ML_DISTANCE_FUNCTIONS_H_
#define _ML_DISTANCE_FUNCTIONS_H_
#include "MLCommon.h"
#include "MLDataSet.h"
#include "MLDataPoint.h"
_MYLABLIB_BEGIN

// Distance Function Type
class IMLDataPointDistanceFunc
{
public:
	virtual ~IMLDataPointDistanceFunc(){};
	virtual double Distance(const CMLDataPoint& p1, const CMLDataPoint& p2) = 0;
};

class CMLEuclideanDistance : public IMLDataPointDistanceFunc
{
public:
	virtual double Distance(const CMLDataPoint& p1, const CMLDataPoint& p2)
	{
		return Dist(p1,p2);
	}

	inline static double Dist(const CMLDataPoint& p1, const CMLDataPoint& p2)
	{
		double dDist = 0.0;
		if (p1.size() != p2.size())
			return -1.0;
		int i;
		for (i=0; i<(int)p1.size(); i++)
		{
			dDist += (p1[i] - p2[i])*(p1[i] - p2[i]);
		}
		return sqrt(dDist);

	}
};

class CMLWeightedEuclideanDistance : public IMLDataPointDistanceFunc
{
public:
	explicit CMLWeightedEuclideanDistance(const CMLDataPoint& weights)
	{
		m_Weights = weights;
	}
	inline void SetWeights(const CMLDataPoint& weights)
	{
		m_Weights = weights;
	}

	inline const CMLDataPoint& GetWeights() const
	{
		return m_Weights;
	}

	inline double GetWeight(int nIndex) const
	{
		return m_Weights[nIndex];
	}

public:
	// Override
	virtual double Distance(const CMLDataPoint& p1, const CMLDataPoint& p2)
	{
		double dDist = 0.0;
		if (p1.size() != p2.size())
			return -1.0;
		int i;
		for (i=0; i<(int)p1.size(); i++)
		{
			dDist += (p1[i] - p2[i])*(p1[i] - p2[i]) * m_Weights[i] * m_Weights[i];
		}
		return sqrt(dDist);
	}

private:
	// Fields
	CMLDataPoint m_Weights;
};




_MYLABLIB_END
#endif
